package com.hoapital.outpbillwork.billWorkHandler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hoapital.outpbillwork.module.controller.vo.ApplyInfo;
import com.hoapital.outpbillwork.module.controller.vo.ItemData;
import com.hoapital.outpbillwork.module.controller.vo.OrderInfo;
import com.hoapital.outpbillwork.module.entity.*;
import com.hoapital.outpbillwork.module.mapper.*;
import com.hoapital.outpbillwork.module.service.ClinicMasterService;
import com.hoapital.outpbillwork.module.service.OutpMedrecService;
import com.hoapital.outpbillwork.module.service.PatVisitService;
import com.hospital.api.RemoteBillService;
import com.hospital.common.core.constants.AllFinalValueUtils;
import com.hospital.common.core.constants.OrderConstant;
import com.hospital.common.core.exception.ExceptionHelp;
import com.hospital.common.core.exception.ExceptionHelpEnum;
import com.hospital.common.core.function.PushMessage;
import com.hospital.common.core.hl7Model.hospitalWork.BATCH;
import com.hospital.common.core.module.controller.dto.BillDto;
import com.hospital.common.core.module.controller.dto.ClinicItem;
import com.hospital.common.core.module.controller.dto.ClinicType;
import com.hospital.common.core.module.controller.vo.DiagnosisInfo;
import com.hospital.common.core.module.controller.vo.OrderContent;
import com.hospital.common.core.module.controller.vo.Receive;
import com.hospital.common.core.module.controller.vo.RegisterInfo;
import com.hospital.common.core.module.entity.query.BillItem;
import com.hospital.common.core.result.ErrorTip;
import com.hospital.common.core.result.SuccessTip;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.DateUtil;
import com.hospital.common.core.utils.SpringContextHolder;
import com.hospital.common.core.utils.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author lvyao
 * @description 开单方法类
 * @date 2022/2/23
 */
@Slf4j
abstract class AbstractOrderWorkBusiness extends AbstractBaseBusiness implements BillWorkHandler {
    @Resource
    private PatientInfoMapper patientInfoMapper = SpringContextHolder.getBean(PatientInfoMapper.class);
    @Resource
    private LabTestMasterMapper labTestMasterMapper = SpringContextHolder.getBean(LabTestMasterMapper.class);

    @Resource
    private ClinicItemDictMapper clinicItemDictMapper = SpringContextHolder.getBean(ClinicItemDictMapper.class);

    @Resource
    private PushMessage pushMessage = SpringContextHolder.getBean(PushMessage.class);

    @Resource
    OutpPrepayRcptTempMapper outpPrepayRcptTempMapper = SpringContextHolder.getBean(OutpPrepayRcptTempMapper.class);

    @Resource
    OrderVsBillnoMapper orderVsBillnoMapper = SpringContextHolder.getBean(OrderVsBillnoMapper.class);
    @Autowired
    private ClinicVsChargeMapper clinicVsChargeMapper = SpringContextHolder.getBean(ClinicVsChargeMapper.class);
    @Resource
    ClinicMasterService clinicMasterService = SpringContextHolder.getBean(ClinicMasterService.class);
    @Resource
    OutpMedrecService outpMedrecService = SpringContextHolder.getBean(OutpMedrecService.class);
    @Resource
    OutpDiagnosisMapper outpDiagnosisMapper = SpringContextHolder.getBean(OutpDiagnosisMapper.class);

    PatVisitService patVisitService = SpringContextHolder.getBean(PatVisitService.class);


    /**
     * @param orderInfo:
     * @param request:
     * @description:门诊之前核酸开单(包括所有门诊数据的补全,同时生成订单除医保外)
     * @author: lvyao
     * @date: 2023/11/9 15:26
     * @return: com.hospital.outpbillwork.response.Tip
     **/
    @Override
    public Tip orderWork(OrderInfo orderInfo, HttpServletRequest request, RemoteBillService remoteBillService) throws ExceptionHelp {
        //从入参中获取患者ID
        PatientInfo patInfo = orderInfo.getPatInfo();
        //从入参中获取患者申请医嘱信息
        List<ApplyInfo> applyInfoList = orderInfo.getApplyInfo();
        //从入参中获取患者诊断信息
        List<DiagnosisInfo> diagnosisDetailList = orderInfo.getDiagnosis();
        //从主索引信息获取患者全部信息
        PatientInfo patientInfo = patientInfoMapper.selectById(patInfo.getPatientId());
        //全接口通用参数检查
        ExceptionHelp exceptionHelp = null;

        //检查入参中数据是否给足
        exceptionHelp = checkOrder(orderInfo, patInfo, applyInfoList, diagnosisDetailList, patientInfo, null, "3");
        if (exceptionHelp != null) {
            throw exceptionHelp;
        }
        int age = DateUtil.getAge(patientInfo.getDateOfBirth());
        Timestamp visitDate = new Timestamp(System.currentTimeMillis());
        int visitNo = Integer.parseInt(labTestMasterMapper.getVisitNo());
        String orderedByDept = applyInfoList.get(0).getOrder().getOrderedByDept();
        String orderedByDoctor = applyInfoList.get(0).getOrder().getOrderedByDoctor();
        String orderedByDoctorId = applyInfoList.get(0).getOrder().getOrderedByDoctorId();
        if (StringUtils.isBlank(orderedByDoctor)) {
            orderedByDoctor = labTestMasterMapper.getDoctorName(orderedByDoctorId);
        }
        int outpId = 0;
        try {
            outpId = labTestMasterMapper.getOutpIdNew(patientInfo.getPatientId(), orderedByDept, orderedByDoctor);
        } catch (Exception e) {
            throw e;
        }
        String visitTime = DateUtil.format(visitDate, "HH:mm");
        //门诊挂号记录
        ClinicMaster clinicMaster = doClinicMaster(patientInfo, diagnosisDetailList, age, visitDate, visitNo, outpId);
        //门诊诊断记录
        OutpMedrec outpMedrec = doOutpMedrec(patientInfo, visitDate, outpId, diagnosisDetailList, visitTime);
        //初始化需要插入表的数据
        List<OutpOrderDescTemp> outpOrderDescTempList = new ArrayList<>();
        //根据处方以及检查检验特殊表获取主表
        List<Object> objectMasterList = new ArrayList<>();
        List<OutpDoctorAssistant> outpDoctorAssistantList = new ArrayList<>();
        List<OutpBillItemsTemp> outpBillItemsTempList = new ArrayList<>();
        //根据处方以及检查检验特殊表获取打包项目明细表
        List<Object> objectDetailList = new ArrayList<>();
        //根据检查计费的特殊性增加计费明细表
        List<Object> objectBillList = new ArrayList<>();
        List<OrderVsBillno> orderVsBillnoList = new ArrayList<>();
        BigDecimal allChargesapply = new BigDecimal("0");
        //组装交易订单记录
        OutpPrepayRcptTemp outpPrepayRcptTemp = doOutpPrepayRcptTemp(patientInfo, allChargesapply, Integer.valueOf(orderInfo.getOutpOrInp()));
        //循环医嘱申请消息
        for (ApplyInfo applyInfo : applyInfoList) {
            OrderContent order = applyInfo.getOrder();
            String tsStr = order.getOrderDate().replace("/", "-");
            visitDate = Timestamp.valueOf(tsStr);
            visitNo = Integer.parseInt(labTestMasterMapper.getVisitNo());
            //医嘱项目信息
            List<ItemData> itemDataList = applyInfo.getItemData();
            //根据检查检验类型获取号若不是检查检验则返回空字符串
            String orderNotemp = getOrderNotemp(order, visitDate, visitNo);

            //获取门诊医嘱临时表
            OutpOrderDescTemp outpOrderDescTemp = doOutpOrderDescTemp(visitDate, patientInfo, visitNo, order, outpId, orderNotemp);
            outpOrderDescTempList.add(outpOrderDescTemp);

            //获取门诊订单包含的明细HIS业务单号数据
            OrderVsBillno orderVsBillno = doOrderVsBillno(outpPrepayRcptTemp.getOrderNo(), visitDate, visitNo, order.getOrderType());
            orderVsBillnoList.add(orderVsBillno);

            //检查表、检验表、处方表的处理
            String testCause = orderInfo.getOutpOrInp().equals(AllFinalValueUtils.OUTP_FLAG) ? AllFinalValueUtils.OUTP_CAUSE : AllFinalValueUtils.INP_CAUSE;
            Object otherInfo = doOtherInfo(itemDataList, orderNotemp, patientInfo, order, age, testCause, diagnosisDetailList.get(0).getDiagName(),
                    visitDate, visitNo, StringUtils.join(itemDataList.stream().map(ItemData::getItemName).collect(Collectors.toList()), "+"), outpId);
            BigDecimal allCosts = new BigDecimal("0");
            BigDecimal allCharges = new BigDecimal("0");
            //循环获取医嘱项目具体信息
            for (ItemData itemData : itemDataList) {
                //查询医嘱项目
                List<ClinicItemDict> clinicItemDictList = getClinicItemDict(testCause, itemData.getItemClass(), itemData.getItemCode(), itemData.getItemSpec());
                BigDecimal itemCosts = new BigDecimal("0");
                BigDecimal itemCharges = new BigDecimal("0");
                //查询医嘱收费项目明细
                String chargeType = getChargeType(orderInfo.getOutpOrInp(), patientInfo.getPatientId(), orderInfo.getVisitId());
                List<ClinicItemBill> clinicItemBillList = getClinicItemBill(chargeType, orderInfo, itemData.getItemClass(), itemData.getItemCode(), itemData.getItemSpec(), remoteBillService);
                //检查检验明细表处理
                int itemNo = itemDataList.indexOf(itemData) + 1;
//                Object objecdetail = doOtherInfoDeatil(orderNotemp, itemNo, itemData.getItemCode(), itemData.getItemName());
                itemData.setOrderNo(orderNotemp);
                itemData.setItemNo(itemNo);
                //处置数据处理
                OutpDoctorAssistant outpDoctorAssistant = doOutpDoctorAssistant(patientInfo, outpId, visitDate, visitTime,
                        itemNo, visitNo, clinicItemDictList, orderNotemp, order, itemData.getAmount(), applyInfo.getOrder().getPerformedBy());
                //循环获取医嘱计费信息
                for (ClinicItemBill clinicItemBill : clinicItemBillList) {
                    //临时计费信息
                    OutpBillItemsTemp outpBillItemsTemp = doOutpBillItemsList(visitDate, visitNo, outpBillItemsTempList.size() + 1, clinicItemBill, itemData);
                    //获取检查的计费表信息
                    Object objectBillDetail = doOtherBillDetail(orderNotemp, outpId, visitDate, visitNo, itemNo, clinicItemBill, itemData, order, patientInfo.getPatientId());
                    //将需要插入表的检查的计费表信息放到List
                    objectBillList.add(objectBillDetail);
                    outpBillItemsTemp.setCosts(itemData.getCosts());
                    outpBillItemsTemp.setCharges(itemData.getCharges());
                    itemCosts = itemCosts.add(itemData.getCosts());
                    itemCharges = itemCharges.add(itemData.getCharges());
                    //将需要插入表的临时收费信息放到List
                    outpBillItemsTempList.add(outpBillItemsTemp);
                }
                outpDoctorAssistant.setCosts(itemCosts);
                outpDoctorAssistant.setCharges(itemCharges);
                //将合计的打包项目费用放入之前的明细项目中
                Object item = doAfterData(OrderConstant.ITEM, itemData, itemCosts, itemCharges);
                //将需要插入表的打包项目表信息放到List
                objectDetailList.add(item);
                allCosts = allCosts.add(itemCosts);
                allCharges = allCharges.add(itemCharges);
                //将需要插入表的门诊处置表信息放到List
                outpDoctorAssistantList.add(outpDoctorAssistant);
            }
            //将检查检验主表中费用加入
            Object master = doAfterData(OrderConstant.MASTER, otherInfo, allCosts, allCharges);
            //将需要插入表的检查检验主表信息放到List
            objectMasterList.add(master);
            allChargesapply.add(allCharges);
            outpPrepayRcptTemp.setAmount(allChargesapply);
        }

        //更新表数据
        boolean push = false;
        boolean updateAllTab = updateAllTab(clinicMaster, outpMedrec, outpOrderDescTempList, outpBillItemsTempList,
                outpDoctorAssistantList, objectMasterList, objectDetailList, objectBillList, outpPrepayRcptTemp, orderVsBillnoList);
        if (updateAllTab) {
            BATCH hl7message = packageMessage(outpMedrec, outpOrderDescTempList, objectMasterList,
                    objectDetailList, orderInfo, patientInfo, AllFinalValueUtils.ORC_1_NEW, AllFinalValueUtils.ORC_5_NEW);
            try {
                //xml申请文件保存并推送
                push = saveApplyHl7message(orderInfo.getHospitalCode(), orderInfo.getHospitalName(), outpPrepayRcptTemp.getOrderNo(), hl7message, OrderConstant.HL7_STATUS_NEW);
            } catch (Exception e) {
                log.error("订单号为:【" + outpPrepayRcptTemp.getOrderNo() + "】xml申请文件转消息发送失败！" + "\r\n异常问题：" + e.getMessage());
            }
        }
        return new SuccessTip(outpPrepayRcptTemp.getOrderNo());
    }

    /**
     * @param orderInfo:
     * @param request:
     * @description:门诊挂号
     * @author: lvyao
     * @date: 2023/11/9 15:26
     * @return: com.hospital.outpbillwork.response.Tip
     **/
    @Override
    public Tip outpRegistWork(OrderInfo orderInfo, HttpServletRequest request) throws ExceptionHelp {
        //从入参中获取患者ID
        PatientInfo patInfo = orderInfo.getPatInfo();
        //组装挂号信息的入参
        List<DiagnosisInfo> diagnosisDetailList = new ArrayList<>();
        //从主索引信息获取患者全部信息
        PatientInfo patientInfo = patientInfoMapper.selectById(patInfo.getPatientId());
        RegisterInfo registerInfo = orderInfo.getRegisterInfo();
        DiagnosisInfo diagnosisInfo = new DiagnosisInfo();
        diagnosisInfo.setClinicType(registerInfo.getClinicType());
        diagnosisInfo.setDiagDept(registerInfo.getVisitDept());
        diagnosisInfo.setDiagDoctor(registerInfo.getVisitDoctor());
        diagnosisInfo.setDiagDoctorId(registerInfo.getVisitDoctorId());
        diagnosisInfo.setFirstVisitIndicator(registerInfo.getFirstVisitIndicator());
        diagnosisDetailList.add(diagnosisInfo);
        //全接口通用参数检查
        ExceptionHelp exceptionHelp = null;

        //检查入参中数据是否给足
        exceptionHelp = checkOrder(orderInfo, patInfo, null, null, patientInfo, registerInfo, "0");
        if (exceptionHelp != null) {
            throw exceptionHelp;
        }
        int age = DateUtil.getAge(patientInfo.getDateOfBirth());
        Timestamp visitDate = new Timestamp(System.currentTimeMillis());
        int visitNo = Integer.parseInt(labTestMasterMapper.getVisitNo());
        String orderedByDept = registerInfo.getVisitDept();
        String orderedByDoctor = registerInfo.getVisitDoctor();
        String orderedByDoctorId = registerInfo.getVisitDoctorId();
        if (StringUtils.isBlank(orderedByDoctor)) {
            orderedByDoctor = labTestMasterMapper.getDoctorName(orderedByDoctorId);
        }
        int outpId = 0;
        try {
            outpId = labTestMasterMapper.getOutpIdNew(patientInfo.getPatientId(), orderedByDept, orderedByDoctor);
        } catch (Exception e) {
            throw e;
        }
        //门诊挂号记录
        ClinicMaster clinicMaster = clinicMasterService.getOne(new QueryWrapper<ClinicMaster>().apply(AllFinalValueUtils.SELECT_CLINIC_MASTER, patientInfo.getPatientId(), orderedByDoctor, orderedByDept, patientInfo.getPatientId()));
        if (ObjectUtil.isNull(clinicMaster)) {
            clinicMaster = doClinicMaster(patientInfo, diagnosisDetailList, age, visitDate, visitNo, outpId);
            //医保挂号门诊表
            Insurance2201 insurance2201 = doInsurance2201(patientInfo, outpId, registerInfo);
            boolean insert = clinicMasterService.insertAll(clinicMaster, insurance2201);
            if (!insert) {
                return new ErrorTip(ExceptionHelpEnum.OUTP_REGIST_ERR);
            }
        }
        return new SuccessTip(clinicMaster);
    }

    /**
     * @param orderInfo:
     * @param request:
     * @description:门诊就诊
     * @author: lvyao
     * @date: 2023/11/9 15:26
     * @return: com.hospital.outpbillwork.response.Tip
     **/
    @Override
    public Tip outpVisitWork(OrderInfo orderInfo, HttpServletRequest request) throws ExceptionHelp {
        //从入参中获取患者ID
        PatientInfo patInfo = orderInfo.getPatInfo();
        //从入参中获取患者诊断信息
        List<DiagnosisInfo> diagnosisDetailList = orderInfo.getDiagnosis();
        //从主索引信息获取患者全部信息
        PatientInfo patientInfo = patientInfoMapper.selectById(patInfo.getPatientId());
        //全接口通用参数检查
        ExceptionHelp exceptionHelp = null;

        //检查入参中数据是否给足
        exceptionHelp = checkOrder(orderInfo, patInfo, null, diagnosisDetailList, patientInfo, null, "1");
        if (exceptionHelp != null) {
            throw exceptionHelp;
        }
        //门诊返回门诊的门诊病历 住院返回入院记录
        if (orderInfo.getOutpOrInp().equals("01")) {
            //门诊诊断记录
            OutpMedrec outpMedrec = outpMedrecService.getOne(new QueryWrapper<OutpMedrec>().eq(AllFinalValueUtils.PATIENT_ID_FIELD_NAME, orderInfo.getPatInfo().getPatientId()).eq(AllFinalValueUtils.OUTP_VISIT_TIME, orderInfo.getVisitId()));
            if (ObjectUtil.isNull(outpMedrec)) {
                Timestamp visitDate = new Timestamp(System.currentTimeMillis());
                int outpId = Integer.valueOf(orderInfo.getVisitId());
                String visitTime = DateUtil.format(visitDate, "HH:mm");
                //门诊诊断记录
                outpMedrec = doOutpMedrec(patientInfo, visitDate, outpId, diagnosisDetailList, visitTime);
                List<OutpDiagnosis> outpDiagnosisList = doOutpDiagnosis(patientInfo, outpId, diagnosisDetailList);
                boolean insert = outpMedrecService.insertAll(outpMedrec, outpDiagnosisList);
                if (!insert) {
                    return new ErrorTip(ExceptionHelpEnum.OUTP_VISIT_ERR);
                }
            }
            return new SuccessTip(outpMedrec);
        } else {
            PatVisit patVisit = patVisitService.getOne(new QueryWrapper<PatVisit>().apply(" patient_id = {0} and visit_id = (select visit_id from pats_in_hospital where patient_id = {1})", patientInfo.getPatientId(), patientInfo.getPatientId()));
            if (StringUtils.isBlank(patientInfo.getInpNo())) {
                return new ErrorTip(ExceptionHelpEnum.INP_VISIT_INFO);
            }
            patVisit.setInpNo(patientInfo.getInpNo());
            return new SuccessTip(patVisit);
        }
    }

    /**
     * @param orderInfo:
     * @param request:
     * @description:最新的门诊开单只有开单不处理门诊挂号及门诊病历数据
     * @author: lvyao
     * @date: 2023/11/9 15:34
     * @return: com.hospital.outpbillwork.response.Tip
     **/
    @Override
    public Tip newOrderWork(OrderInfo orderInfo, ClinicMaster clinicMaster, OutpMedrec outpMedrec, ApplyInfo applyInfo, HttpServletRequest request, RemoteBillService remoteBillService) throws ExceptionHelp {
        //从入参中获取患者ID
        PatientInfo patInfo = orderInfo.getPatInfo();
        //从入参中获取患者申请医嘱信息
        List<ApplyInfo> applyInfoList = orderInfo.getApplyInfo();
        //从主索引信息获取患者全部信息
        PatientInfo patientInfo = patientInfoMapper.selectById(patInfo.getPatientId());
        //全接口通用参数检查
        ExceptionHelp exceptionHelp = null;
        //检查入参中数据是否给足
        exceptionHelp = checkOrder(orderInfo, patInfo, applyInfoList, null, patientInfo, null, "2");
        if (exceptionHelp != null) {
            throw exceptionHelp;
        }
        int age = DateUtil.getAge(patientInfo.getDateOfBirth());
        Timestamp visitDate = new Timestamp(System.currentTimeMillis());
        int visitNo = Integer.parseInt(labTestMasterMapper.getVisitNo());
        int outpId = Integer.valueOf(orderInfo.getVisitId());
        //从入参中获取患者诊断信息
        List<OutpDiagnosis> diagnosisDetailList = outpDiagnosisMapper.selectList(new QueryWrapper<OutpDiagnosis>().eq(AllFinalValueUtils.PATIENT_ID_FIELD_NAME, patientInfo.getPatientId()).eq(AllFinalValueUtils.OUTP_VISIT_TIME, String.valueOf(outpId)));
        if (CollectionUtils.isEmpty(diagnosisDetailList)) {
            throw new ExceptionHelp(ExceptionHelpEnum.NULL_DIAGS);
        }
        String visitTime = DateUtil.format(visitDate, "HH:mm");
        //初始化需要插入表的数据
        List<OutpOrderDescTemp> outpOrderDescTempList = new ArrayList<>();
        //根据处方以及检查检验特殊表获取主表
        List<Object> objectMasterList = new ArrayList<>();
        List<OutpDoctorAssistant> outpDoctorAssistantList = new ArrayList<>();
        List<OutpBillItemsTemp> outpBillItemsTempList = new ArrayList<>();
        //根据处方以及检查检验特殊表获取打包项目明细表
        List<Object> objectDetailList = new ArrayList<>();
        //根据检查计费的特殊性增加计费明细表
        List<Object> objectBillList = new ArrayList<>();
        List<OrderVsBillno> orderVsBillnoList = new ArrayList<>();
        BigDecimal allChargesapply = new BigDecimal("0");
        //组装交易订单记录
        OutpPrepayRcptTemp outpPrepayRcptTemp = doOutpPrepayRcptTemp(patientInfo, allChargesapply, Integer.valueOf(orderInfo.getOutpOrInp()));
        //循环医嘱申请消息
        OrderContent order = applyInfo.getOrder();
        String tsStr = order.getOrderDate().replace("/", "-");
        visitDate = Timestamp.valueOf(tsStr);
        //医嘱项目信息
        List<ItemData> itemDataList = applyInfo.getItemData();
        if (CollectionUtils.isEmpty(itemDataList)) {
            throw new ExceptionHelp(ExceptionHelpEnum.VALIDATOR_MAP);
        }
        //根据检查检验类型获取号若不是检查检验则返回空字符串
        String orderNotemp = getOrderNotemp(order, visitDate, visitNo);
        //获取门诊医嘱临时表
        OutpOrderDescTemp outpOrderDescTemp = doOutpOrderDescTemp(visitDate, patientInfo, visitNo, order, outpId, orderNotemp);
        outpOrderDescTempList.add(outpOrderDescTemp);
        //获取门诊订单包含的明细HIS业务单号数据
        OrderVsBillno orderVsBillno = doOrderVsBillno(outpPrepayRcptTemp.getOrderNo(), visitDate, visitNo, order.getOrderType());
        orderVsBillnoList.add(orderVsBillno);
        //检查表、检验表、处方表的处理
        String testCause = orderInfo.getOutpOrInp().equals(AllFinalValueUtils.OUTP_FLAG) ? AllFinalValueUtils.OUTP_CAUSE : AllFinalValueUtils.INP_CAUSE;
        Object otherInfo = doOtherInfo(itemDataList, orderNotemp, patientInfo, order, age, testCause, diagnosisDetailList.get(0).getDiagName(),
                visitDate, visitNo, StringUtils.join(itemDataList.stream().map(ItemData::getItemName).collect(Collectors.toList()), "+"), outpId);
        BigDecimal allCosts = new BigDecimal("0");
        BigDecimal allCharges = new BigDecimal("0");
        //循环获取医嘱项目具体信息
        for (ItemData itemData : itemDataList) {
            String itemCode = itemData.getItemCode();
            String itemSpec = itemData.getItemSpec();
            if (itemData.getItemClass().equals(AllFinalValueUtils.MATERIAL)) {
                itemCode = clinicItemDictMapper.selectOrderMaterial(itemCode, itemSpec);
            }
            //查询医嘱项目
            List<ClinicItemDict> clinicItemDictList = getClinicItemDict(testCause, itemData.getItemClass(), itemCode, itemSpec);
            BigDecimal itemCosts = new BigDecimal("0");
            BigDecimal itemCharges = new BigDecimal("0");
            //查询医嘱收费项目明细
            String chargeType = getChargeType(orderInfo.getOutpOrInp(), patientInfo.getPatientId(), orderInfo.getVisitId());
            List<ClinicItemBill> clinicItemBillList = getClinicItemBill(chargeType, orderInfo, itemData.getItemClass(), itemCode, itemSpec, remoteBillService);
            //检查检验明细表处理
            int itemNo = itemDataList.indexOf(itemData) + 1;
            itemData.setOrderNo(orderNotemp);
            itemData.setItemNo(itemNo);
            itemData.setVisitDate(visitDate);
            itemData.setVisitNo(visitNo);
            itemData.setOutpId(outpId);
            itemData.setPatientId(patientInfo.getPatientId());
            itemData.setOrderContent(order);
            //处置数据处理
            OutpDoctorAssistant outpDoctorAssistant = doOutpDoctorAssistant(patientInfo, outpId, visitDate, visitTime,
                    itemNo, visitNo, clinicItemDictList, orderNotemp, order, itemData.getAmount(), applyInfo.getOrder().getPerformedBy());
            //循环获取医嘱计费信息
            for (ClinicItemBill clinicItemBill : clinicItemBillList) {
                itemData.setClinicItemBill(clinicItemBill);
                //临时计费信息
                OutpBillItemsTemp outpBillItemsTemp = doOutpBillItemsList(visitDate, visitNo, outpBillItemsTempList.size() + 1, clinicItemBill, itemData);
                //获取检查的计费表信息
                Object objectBillDetail = doOtherBillDetail(orderNotemp, outpId, visitDate, visitNo, itemNo, clinicItemBill, itemData, order, patientInfo.getPatientId());
                //将需要插入表的检查的计费表信息放到List
                objectBillList.add(objectBillDetail);
                BigDecimal price = ObjectUtil.isNull(clinicItemBill.getPrice()) ? BigDecimal.ZERO : clinicItemBill.getPrice();
                outpBillItemsTemp.setCosts(ObjectUtil.isNull(clinicItemBill.getCosts()) ? price : clinicItemBill.getCosts());
                outpBillItemsTemp.setCharges(ObjectUtil.isNull(clinicItemBill.getCharges()) ? price : clinicItemBill.getCharges());
                itemCosts = itemCosts.add(outpBillItemsTemp.getCosts());
                itemCharges = itemCharges.add(outpBillItemsTemp.getCharges());
                //将需要插入表的临时收费信息放到List
                outpBillItemsTempList.add(outpBillItemsTemp);
            }
            outpDoctorAssistant.setCosts(itemCosts);
            outpDoctorAssistant.setCharges(itemCharges);
            if (itemData.getItemClass().equals(AllFinalValueUtils.MATERIAL)) {
                outpDoctorAssistant.setItemSpec(itemSpec);
                outpDoctorAssistant.setUnits(clinicItemDictList.get(0).getUnits());
            }
            //将合计的打包项目费用放入之前的明细项目中
            Object item = doAfterData(OrderConstant.ITEM, itemData, itemCosts, itemCharges);
            //将需要插入表的打包项目表信息放到List
            objectDetailList.add(item);
            allCosts = allCosts.add(itemCosts);
            allCharges = allCharges.add(itemCharges);
            //将需要插入表的门诊处置表信息放到List
            outpDoctorAssistantList.add(outpDoctorAssistant);
        }
        //将检查检验主表中费用加入
        Object master = doAfterData(OrderConstant.MASTER, otherInfo, allCosts, allCharges);
        //将需要插入表的检查检验主表信息放到List
        objectMasterList.add(master);
        allChargesapply.add(allCharges);
        outpPrepayRcptTemp.setAmount(allChargesapply);
        outpPrepayRcptTemp.setCreateChannel(orderInfo.getCreateChannel());
        //更新表数据
        boolean push = false;
        boolean updateAllTab = updateAllTab(null, null, outpOrderDescTempList, outpBillItemsTempList,
                outpDoctorAssistantList, objectMasterList, objectDetailList, objectBillList, outpPrepayRcptTemp, orderVsBillnoList);
        if (updateAllTab) {
            BATCH hl7message = packageMessage(outpMedrec, outpOrderDescTempList, objectMasterList,
                    objectDetailList, orderInfo, patientInfo, AllFinalValueUtils.ORC_1_NEW, AllFinalValueUtils.ORC_5_NEW);
            try {
                //xml申请文件保存并推送
                push = saveApplyHl7message(orderInfo.getHospitalCode(), orderInfo.getHospitalName(), outpPrepayRcptTemp.getOrderNo(), hl7message, OrderConstant.HL7_STATUS_NEW);
            } catch (Exception e) {
                log.error("订单号为:【" + outpPrepayRcptTemp.getOrderNo() + "】xml申请文件转消息发送失败！" + "\r\n异常问题：" + e.getMessage());
            }
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hisBillNo", orderVsBillnoList.stream().map(OrderVsBillno::getOrderNo).collect(Collectors.toList()));
        return new SuccessTip(jsonObject);
    }

    /**
     * @param patientId:
     * @param visitTiem:
     * @description:获取费别
     * @author: lvyao
     * @date: 2024/2/28 11:27
     * @return: java.lang.String
     **/
    public String getChargeType(String outpOrInp, String patientId, String visitTiem) {
        String chargeType = visitTiem == null || visitTiem.trim().equals("") ? clinicVsChargeMapper.getPatChargeType(patientId) : outpOrInp.equals("02") ? clinicVsChargeMapper.getChargeTypeInp(patientId, visitTiem) : clinicVsChargeMapper.getChargeType(patientId, visitTiem);
        if (chargeType == null || chargeType.isEmpty()) {
            chargeType = "自费";
        }
        return chargeType;
    }

    /**
     * 检查入参中信息是否充足
     *
     * @param patInfo             入参的患者基本信息
     * @param applyInfoList       医嘱申请消息
     * @param diagnosisDetailList 诊断就诊消息
     * @param patientInfo         查表获取的患者基本信息
     * @param registerInfo        挂号信息
     * @param type                0-挂号入参检查 1-门诊就诊信息 2-门诊开单信息 3-旧的一键核酸
     * @return
     */
    public ExceptionHelp checkOrder(OrderInfo orderInfo, PatientInfo patInfo,
                                    List<ApplyInfo> applyInfoList,
                                    List<DiagnosisInfo> diagnosisDetailList,
                                    PatientInfo patientInfo, RegisterInfo registerInfo, String type) throws ExceptionHelp {
        ExceptionHelp exceptionHelp = null;
        if (ObjectUtil.isNull(patInfo)) {
            return new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_INP_PAT);
        }
        if (type.equals("2") || type.equals("3")) {
            if (applyInfoList.isEmpty()) {
                return new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_INP_ORDER);
            }
            for (ApplyInfo applyInfo : orderInfo.getApplyInfo()) {
                String performedBy = applyInfo.getOrder().getPerformedBy();
                if (StringUtils.isBlank(performedBy)) {
                    return new ExceptionHelp(ExceptionHelpEnum.NULL_PERFORM);
                }
                //检查检验处方等开单的必填字段单独处理
                exceptionHelp = checkOtherExpecOrder(applyInfo);
                if (ObjectUtil.isNotNull(exceptionHelp)) {
                    return exceptionHelp;
                }
                //明细执行科室
                List<ItemData> itemDataList = applyInfo.getItemData();
                for (ItemData itemData : itemDataList) {
                    if (StringUtils.isBlank(itemData.getPerformedBy())) {
                        return new ExceptionHelp(ExceptionHelpEnum.NULL_PERFORM);
                    }
                    if (ObjectUtil.isNull(itemData.getAmount())) {
                        return new ExceptionHelp(ExceptionHelpEnum.NULL_AMOUNT);
                    }
                }
            }
        }
        if (type.equals("0")) {
            if (ObjectUtil.isNull(registerInfo)) {
                return new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_INP_ORDER);
            }
        }
        if (type.equals("1") || type.equals("3")) {
            if (diagnosisDetailList.isEmpty() || diagnosisDetailList.size() > 1) {
                if (diagnosisDetailList.get(0).getClinicType() == null || diagnosisDetailList.get(0).getClinicType().trim().equals("") ||
                        diagnosisDetailList.get(0).getDiagDept() == null || diagnosisDetailList.get(0).getDiagDept().trim().equals("") ||
                        diagnosisDetailList.get(0).getDiagDoctor() == null || diagnosisDetailList.get(0).getDiagDoctor().trim().equals("") ||
                        diagnosisDetailList.get(0).getDiagDoctor() == null || diagnosisDetailList.get(0).getDiagDoctor().trim().equals("") ||
                        diagnosisDetailList.get(0).getDiagDoctor() == null || diagnosisDetailList.get(0).getDiagDoctor().trim().equals("") ||
                        diagnosisDetailList.get(0).getDiagDoctorId() == null || diagnosisDetailList.get(0).getDiagDoctorId().trim().equals("") ||
                        diagnosisDetailList.get(0).getFirstVisitIndicator() == null || diagnosisDetailList.get(0).getFirstVisitIndicator().trim().equals("")) {
                    return new ExceptionHelp(ExceptionHelpEnum.DIAG_ERR_FILDS);
                }
                return new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_INP_DIAG);
            }
        }
        if (ObjectUtil.isNull(patientInfo)) {
            return new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_INP_PATTABLE);
        }
        exceptionHelp = checkOtherOrder(orderInfo);
        if (ObjectUtil.isNotNull(exceptionHelp)) {
            return exceptionHelp;
        }
        return null;
    }

    /**
     * 检查、检验、处方、特殊类开单检查的参数
     *
     * @param orderInfo
     * @return
     * @throws ExceptionHelp
     */
    public abstract ExceptionHelp checkOtherOrder(OrderInfo orderInfo) throws ExceptionHelp;

    public abstract ExceptionHelp checkOtherExpecOrder(ApplyInfo orderInfo) throws ExceptionHelp;

    public abstract String getOrderNotemp(OrderContent orderContent, Timestamp visitDate, int visitNo) throws ExceptionHelp;

    /**
     * 生成门诊挂号记录
     *
     * @param patientInfo
     * @param diagnosisDetailList
     * @param age
     * @param visitDate
     * @param visitNo
     * @param outpId
     * @return
     */
    public ClinicMaster doClinicMaster(PatientInfo patientInfo,
                                       List<DiagnosisInfo> diagnosisDetailList, int age,
                                       Timestamp visitDate, int visitNo, int outpId) throws ExceptionHelp {
        //组装门诊挂号记录
        ClinicMaster clinicMaster = new ClinicMaster();
        clinicMaster.setPatientId(patientInfo.getPatientId());
        clinicMaster.setVisitDate(visitDate);
        clinicMaster.setVisitNo(visitNo);
        clinicMaster.setPayWay("1");
        clinicMaster.setRegistFee(new BigDecimal(0));
        clinicMaster.setClinicFee(new BigDecimal(0));
        clinicMaster.setClinicCharge(new BigDecimal(0));
        clinicMaster.setOtherFee(new BigDecimal(0));
        clinicMaster.setOutpId(outpId);
        clinicMaster.setName(patientInfo.getName());
        clinicMaster.setNamePhonetic(patientInfo.getNamePhonetic());
        clinicMaster.setSex(patientInfo.getSex());
        clinicMaster.setAge(age);
        clinicMaster.setIdentity(patientInfo.getIdentity());
        clinicMaster.setChargeType(patientInfo.getChargeType());
        clinicMaster.setUnitInContract(patientInfo.getUnitInContract());
        clinicMaster.setClinicType(diagnosisDetailList.get(0).getClinicType());
        clinicMaster.setVisitDept(diagnosisDetailList.get(0).getDiagDept());
        clinicMaster.setDoctor(diagnosisDetailList.get(0).getDiagDoctor());
        clinicMaster.setRegistrationStatus(3);
        clinicMaster.setRegisteringDate(visitDate);
        clinicMaster.setOperator(diagnosisDetailList.get(0).getDiagDoctor());
        clinicMaster.setDoctor(diagnosisDetailList.get(0).getDiagDoctor());
        clinicMaster.setDoctorId(diagnosisDetailList.get(0).getDiagDoctorId());
        clinicMaster.setFirstVisitIndicator(Integer.parseInt(diagnosisDetailList.get(0).getFirstVisitIndicator()));
        return clinicMaster;
    }

    /**
     * 组装订单数据
     *
     * @param patientInfo
     * @return
     */
    public OutpPrepayRcptTemp doOutpPrepayRcptTemp(PatientInfo patientInfo, BigDecimal allApplyCharges, int inpOrOutp) throws ExceptionHelp {
        OutpPrepayRcptTemp outpPrepayRcptTemp = new OutpPrepayRcptTemp();
        outpPrepayRcptTemp.setPatientId(patientInfo.getPatientId());
        String orderNumber = UUID.randomUUID().toString().replace("-", "");
        String guid = labTestMasterMapper.getGuid();
        outpPrepayRcptTemp.setGuid(guid);
        outpPrepayRcptTemp.setInpOrOutp(String.valueOf(inpOrOutp));
        outpPrepayRcptTemp.setAmount(allApplyCharges);
        outpPrepayRcptTemp.setOrderNo(orderNumber);
        outpPrepayRcptTemp.setReturnAmount(new BigDecimal("0"));
        outpPrepayRcptTemp.setPayWay("微信");
        outpPrepayRcptTemp.setTransactType("结算");
        outpPrepayRcptTemp.setHisTransactDate(Timestamp.valueOf(DateUtil.getTime()));
        outpPrepayRcptTemp.setHisTranStatus("1");
        outpPrepayRcptTemp.setSettleFlag("0");
        return outpPrepayRcptTemp;
    }

    /**
     * 组装门诊诊断信息
     *
     * @param patientInfo
     * @param visitDate
     * @param outpId
     * @param diagnosisDetailList
     * @param visitTime
     * @return
     */
    public OutpMedrec doOutpMedrec(PatientInfo patientInfo, Timestamp visitDate, int outpId,
                                   List<DiagnosisInfo> diagnosisDetailList, String visitTime) throws ExceptionHelp {
        OutpMedrec outpMedrec = new OutpMedrec();
        //循环诊断信息
        for (DiagnosisInfo diagnosisDetail : diagnosisDetailList) {
            //组装门诊诊断信息
            outpMedrec.setVisitDate(visitDate);
            outpMedrec.setPatientId(patientInfo.getPatientId());
            outpMedrec.setOutpId(outpId);
            outpMedrec.setVisitTime(visitTime);
            outpMedrec.setDept(diagnosisDetail.getDiagDept());
            outpMedrec.setDoctor(diagnosisDetail.getDiagDoctor());
            outpMedrec.setNotes(diagnosisDetail.getNotes());
            outpMedrec.setPatientCondition(diagnosisDetail.getPatientCondition());
            outpMedrec.setResult(diagnosisDetail.getDiagName());
            outpMedrec.setSymptom(diagnosisDetail.getSymptom());
            outpMedrec.setPhysical(diagnosisDetail.getPhysical());
            outpMedrec.setPresentIllness(diagnosisDetail.getPresentIllness());
            outpMedrec.setPastIllness(diagnosisDetail.getPastIllness());
            outpMedrec.setAuxExamResults(diagnosisDetail.getAuxExamResults());
            outpMedrec.setDiagCode(diagnosisDetail.getDiagCode());
        }
        return outpMedrec;
    }

    /**
     * 组装门诊医嘱临时表数据
     *
     * @param visitDate
     * @param patientInfo
     * @param visitNo
     * @param order
     * @param outpId
     * @param testNo
     * @return
     */
    public OutpOrderDescTemp doOutpOrderDescTemp(Timestamp visitDate, PatientInfo patientInfo,
                                                 int visitNo, OrderContent order, int outpId, String testNo) throws ExceptionHelp {
        OutpOrderDescTemp outpOrderDescTemp = new OutpOrderDescTemp();
        outpOrderDescTemp.setVisitDate(visitDate);
        outpOrderDescTemp.setVisitNo(visitNo);
        outpOrderDescTemp.setPatientId(patientInfo.getPatientId());
        outpOrderDescTemp.setOrderedByDept(order.getOrderedByDept());
        outpOrderDescTemp.setOrderedByDoctor(order.getOrderedByDoctor());
        outpOrderDescTemp.setPrescIndicator(order.getOrderType().equals(AllFinalValueUtils.EAST_DRUG) ? 1 : order.getOrderType().equals(AllFinalValueUtils.WEST_DRUG) ? 2 : 0);
        outpOrderDescTemp.setOutpId(outpId);
        outpOrderDescTemp.setOrderNo(testNo);
        outpOrderDescTemp.setOrderType(order.getOrderType());
        outpOrderDescTemp.setUserId(order.getUserId());
        outpOrderDescTemp.setDoctorId(order.getOrderedByDoctorId());
        return outpOrderDescTemp;
    }

    /**
     * 门诊订单与HIS业务单号对照表
     *
     * @param orderNumber
     * @param visitDate
     * @param visitNo
     * @return
     * @throws ExceptionHelp
     */
    public OrderVsBillno doOrderVsBillno(String orderNumber, Timestamp visitDate, int visitNo, String orderType) throws ExceptionHelp {
        OrderVsBillno orderVsBillno = new OrderVsBillno();
        orderVsBillno.setOrderNo(orderNumber);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String billNumber = df.format(visitDate) + visitNo;
        orderVsBillno.setBillNo(billNumber);
        orderVsBillno.setOrderType(orderType);
        return orderVsBillno;
    }

    /**
     * 处理门诊挂号医保信息表
     *
     * @param patientInfo
     * @param outpId
     * @param registerInfo
     * @return
     */
    public Insurance2201 doInsurance2201(PatientInfo patientInfo, int outpId, RegisterInfo registerInfo) throws ExceptionHelp {
        Insurance2201 insurance2201 = new Insurance2201();
        insurance2201.setBegntime(DateUtil.nowDate());
        String iptOtp = patientInfo.getPatientId() + String.valueOf(outpId);
        insurance2201.setIptOtpNo(iptOtp);
        insurance2201.setAtddrNo(registerInfo.getVisitDoctorId());
        insurance2201.setDrName(registerInfo.getVisitDoctor());
        insurance2201.setDeptCode(registerInfo.getVisitDept());
        //获取医保对照后的科室科别
        RegisterInfo byvisitCode = labTestMasterMapper.getByvisitCode(registerInfo.getVisitDept());
        insurance2201.setDeptName(byvisitCode.getVisitDeptName());
        insurance2201.setCaty(byvisitCode.getVisitDept());
        insurance2201.setPatientId(patientInfo.getPatientId());
        insurance2201.setOutpId(outpId);
        return insurance2201;
    }

    /**
     * 处理门诊挂号医保信息表
     *
     * @param patientInfo
     * @param outpId
     * @param diagnosisDetailList
     * @return
     */
    public List<OutpDiagnosis> doOutpDiagnosis(PatientInfo patientInfo, int outpId, List<DiagnosisInfo> diagnosisDetailList) throws ExceptionHelp {
        List<OutpDiagnosis> outpDiagnosisList = new ArrayList<>();
        for (DiagnosisInfo diagnosisInfo : diagnosisDetailList) {
            OutpDiagnosis outpDiagnosis = new OutpDiagnosis();
            outpDiagnosis.setPatientId(patientInfo.getPatientId());
            outpDiagnosis.setOutpId(outpId);
            outpDiagnosis.setDiagType(diagnosisInfo.getDiagType());
            outpDiagnosis.setDiagSrtNo(diagnosisDetailList.indexOf(diagnosisInfo) + 1);
            outpDiagnosis.setDiagCode(diagnosisInfo.getDiagCode());
            outpDiagnosis.setDiagName(diagnosisInfo.getDiagName());
            outpDiagnosis.setDiagDept(diagnosisInfo.getDiagDept());
            outpDiagnosis.setDiseDorNo(labTestMasterMapper.getDoctorUserId(diagnosisInfo.getDiagDoctorId()));
            outpDiagnosis.setDiseDorName(labTestMasterMapper.getDoctorName(diagnosisInfo.getDiagDoctorId()));
            outpDiagnosis.setDiagTime(DateUtil.nowDate());
            outpDiagnosisList.add(outpDiagnosis);
        }
        return outpDiagnosisList;
    }

    /**
     * 处理门诊其它信息表（检查检验以及处方等）
     *
     * @param itemDataList
     * @param testNo
     * @param patientInfo
     * @param order
     * @param age
     * @param testCause
     * @param clininDiag
     * @param visitDate
     * @return
     */
    protected abstract Object doOtherInfo(List<ItemData> itemDataList, String testNo, PatientInfo patientInfo,
                                          OrderContent order, int age, String testCause,
                                          String clininDiag, Timestamp visitDate, int visitNo, String subject, int outpId) throws ExceptionHelp;

    /**
     * 获得检查检验特殊表的项目明细表
     *
     * @param orderNo
     * @param itemNo
     * @param itemCode
     * @param itemName
     * @return
     */
    protected abstract Object doOtherInfoDeatil(String orderNo, int itemNo, String itemCode, String itemName, BigDecimal price, BigDecimal charges);

    /**
     * 消息体封装
     *
     * @return
     */
    protected abstract BATCH packageMessage(OutpMedrec outpMedrec, List<OutpOrderDescTemp> outpOrderDescTempList,
                                            List<Object> objectMaster, List<Object> objectDetail, OrderInfo orderInfo,
                                            PatientInfo patientInfo, String orc1, String orc5) throws ExceptionHelp;


    /**
     * 获取打包项目其余数据信息
     *
     * @param testCauser
     * @param itemClass
     * @param itemCode
     * @return
     */
    public List<ClinicItemDict> getClinicItemDict(String testCauser, String itemClass, String itemCode, String itemSpec) throws ExceptionHelp {
        QueryWrapper<ClinicItemDict> clinicItemDictQueryWrapper = new QueryWrapper<>();
        clinicItemDictQueryWrapper.apply(" item_class = {0}\n" +
                "   And (Category Like '%" + testCauser + "%' or Category is null) \n" +
                "   And (( item_class ='C'  and rank Is Not Null) or ( item_class <>'C'  and  rank is null)) \n" +
                "   And (is_using <> '停用' or is_using is null)\n" +
                "   And item_code = {1}", itemClass, itemCode);
        List<ClinicItemDict> clinicItemDictList = clinicItemDictMapper.selectList(clinicItemDictQueryWrapper);
        if (clinicItemDictList.isEmpty() || CollectionUtils.isEmpty(clinicItemDictList)) {
            clinicItemDictList = clinicItemDictMapper.selectBillList(itemCode, itemSpec);
        }
        return clinicItemDictList;
    }

    /**
     * 获取打包项目的收费项目
     *
     * @param itemCode
     * @return
     * @throws ExceptionHelp
     */
    public List<ClinicItemBill> getClinicItemBill(String chargeType, OrderInfo orderInfo, String itemClass, String itemCode, String itemSpec, RemoteBillService remoteBillService) throws ExceptionHelp {
        //获取打折后费用明细
        List<ClinicItemBill> clinicItemBillList = new ArrayList<>();
        List<ClinicItemBill> finalClinicItemBillList = clinicItemBillList;
        String billDiscountUrl = labTestMasterMapper.getBillDiscountUrl();
        BillDto billDto = new BillDto();
        BeanUtil.copyProperties(orderInfo, billDto);
        billDto.setChargeType(chargeType);
        List<ClinicType> clinicTypeList = new ArrayList<>();
        ClinicType clinicType = new ClinicType();
        clinicType.setType(itemClass);
        List<ClinicItem> clinicItemList = new ArrayList<>();
        ClinicItem clinicItem = new ClinicItem();
        clinicItem.setClinicItemCode(itemCode);
        clinicItem.setAmount(new BigDecimal("1"));
        clinicItem.setPrimaryDate(DateUtil.getTime());
        clinicItemList.add(clinicItem);
        clinicType.setClinicItemList(clinicItemList);
        clinicTypeList.add(clinicType);
        billDto.setClinicTypeList(clinicTypeList);
        BillDto billDiscountList = remoteBillService.getBillDiscountList(JSONObject.toJSONString(billDto), null);
        if (ObjectUtil.isNotNull(billDiscountList)) {
            List<ClinicItem> clinicItemList1 = billDiscountList.getClinicTypeList().get(0).getClinicItemList();
            clinicItemList1.stream().forEach(clinicItem1 -> {
                List<BillItem> billItemList = clinicItem1.getBillItemList();
                billItemList.stream().forEach(billItem -> {
                    ClinicItemBill clinicItemBill = new ClinicItemBill();
                    BeanUtil.copyProperties(billItem, clinicItemBill);
                    clinicItemBill.setChargeItemNo(Integer.valueOf(billItem.getItemNo()));
                    finalClinicItemBillList.add(clinicItemBill);
                });
            });
            //此处else打折若查询不到按原价开单
        } else {
            //全自费时下面一句代码
            clinicItemBillList = labTestMasterMapper.getBillList(itemCode, itemSpec);
        }
        if (clinicItemBillList.isEmpty()) {
            clinicItemBillList = labTestMasterMapper.getBillListMaterial(itemCode, itemSpec);
            if (clinicItemBillList.isEmpty()) {
                throw new ExceptionHelp(ExceptionHelpEnum.LAB_ORDER_BILLITEMS);
            }
        }

        return clinicItemBillList;
    }

    /**
     * 生成门诊处置表信息
     *
     * @param patientInfo
     * @param outpId
     * @param visitDate
     * @param visitTime
     * @param itemNo
     * @param visitNo
     * @param clinicItemDictList
     * @param testNo
     * @param order
     * @param amount
     * @return
     */
    public OutpDoctorAssistant doOutpDoctorAssistant(PatientInfo patientInfo, int outpId, Timestamp
            visitDate, String visitTime, int itemNo, int visitNo
            , List<ClinicItemDict> clinicItemDictList, String testNo, OrderContent order, BigDecimal amount, String
                                                             performedBy) throws ExceptionHelp {
        OutpDoctorAssistant outpDoctorAssistant = new OutpDoctorAssistant();
        outpDoctorAssistant.setPatientId(patientInfo.getPatientId());
        outpDoctorAssistant.setOutpId(outpId);
        outpDoctorAssistant.setVisitDate(visitDate);
        outpDoctorAssistant.setVisitTime(visitTime);
        outpDoctorAssistant.setVisitNo(visitNo);
        outpDoctorAssistant.setItemNo(itemNo);
        outpDoctorAssistant.setItemClass(clinicItemDictList.get(0).getItemClass());
        outpDoctorAssistant.setItemCode(clinicItemDictList.get(0).getItemCode());
        outpDoctorAssistant.setItemName(clinicItemDictList.get(0).getItemName());
        outpDoctorAssistant.setPerformedBy(performedBy);
        outpDoctorAssistant.setIds(testNo);
        outpDoctorAssistant.setDept(order.getOrderedByDept());
        outpDoctorAssistant.setDoctor(order.getOrderedByDoctor());
        outpDoctorAssistant.setChargeFlag(0);
        outpDoctorAssistant.setAmount(amount);
        return outpDoctorAssistant;
    }

    /**
     * 生成门诊临时计费数据
     *
     * @param visitDate
     * @param visitNo
     * @param itemNo
     * @param clinicItemBill
     * @param itemData
     * @return
     * @throws ExceptionHelp
     */
    public OutpBillItemsTemp doOutpBillItemsList(Timestamp visitDate, int visitNo, int itemNo, ClinicItemBill
            clinicItemBill, ItemData itemData) throws ExceptionHelp {
        OutpBillItemsTemp outpBillItemsTemp = new OutpBillItemsTemp();
        outpBillItemsTemp.setVisitDate(visitDate);
        outpBillItemsTemp.setVisitNo(visitNo);
        outpBillItemsTemp.setItemNo(itemNo);
        outpBillItemsTemp.setItemClass(clinicItemBill.getItemClass());
        outpBillItemsTemp.setClassOnRcpt(clinicItemBill.getClassOnOutpRcpt());
        outpBillItemsTemp.setItemCode(clinicItemBill.getItemCode());
        outpBillItemsTemp.setItemName(clinicItemBill.getItemName());
        outpBillItemsTemp.setItemSpec(clinicItemBill.getItemSpec());
        outpBillItemsTemp.setAmount(ObjectUtil.isNull(clinicItemBill.getAmount()) ? itemData.getAmount() : clinicItemBill.getAmount().multiply(itemData.getAmount()));
        outpBillItemsTemp.setUnits(clinicItemBill.getUnits());
        outpBillItemsTemp.setPerformedBy(itemData.getPerformedBy());
        if (itemData.getCosts() == null || itemData.getCharges() == null) {
            throw new ExceptionHelp(ExceptionHelpEnum.ITEM_NULL_COSTS);
        }
        return outpBillItemsTemp;
    }

    /**
     * 检查计费多余表
     *
     * @param testNo
     * @param outpId
     * @param visitDate
     * @param itemNo
     * @param clinicItemBill
     * @param itemData
     * @param orderContent
     * @return
     */
    public abstract Object doOtherBillDetail(String testNo, int outpId, Timestamp visitDate, int visitNo, int itemNo,
                                             ClinicItemBill clinicItemBill, ItemData itemData, OrderContent orderContent, String patientId) throws
            ExceptionHelp;

    /**
     * 后获得数据处理例如检验后面总费用需要填写到前面生成的检验主表中等
     *
     * @param costs
     * @param charges
     * @return
     */
    public abstract Object doAfterData(String type, Object object, BigDecimal costs, BigDecimal charges) throws
            ExceptionHelp;

    /**
     * 将转换的xml文件保存并转换成HL7推送
     *
     * @param hosCode
     * @param hosName
     * @param orderNotemp
     * @param getHl7LabMessage
     * @return
     */
    public boolean saveApplyHl7message(String hosCode, String hosName, String orderNotemp, BATCH
            getHl7LabMessage, String type) throws ExceptionHelp {
        //直接存为xml文件 中间多节点 labHl7Orders
        String convertToXml = getReplaceString(getHl7LabMessage);
        Map<String, String> hl7InterConfig = getHl7InterConfig(getHl7LabMessage.getType());
        //XML_HL7_FILE  XML_HL7_URL  WX_HL7_POST_URL
        String filePath = hl7InterConfig.get("filePath");
        String postHl7Url = hl7InterConfig.get("postHl7Url");
        String xmlHl7Url = hl7InterConfig.get("xmlHl7Url");
        filePath += orderNotemp + ".xml";
        boolean string2File = XMLUtil.string2File(convertToXml, filePath);
        if (!string2File) {
            throw new ExceptionHelp(ExceptionHelpEnum.HL7_XMLFILE_FILDS);
        }
        //推送申请
        try {
            pushMessage.sendLabApplyInfo(hosCode, hosName, xmlHl7Url, filePath, postHl7Url, type == null || type.equals("") ? "0" : type);
        } catch (ExceptionHelp e) {
            throw e;
        }
        return true;
    }

    @Override
    public Tip sendBillHl7Msg(String hosCode, String hosName, String oneKey, String type, String hl7Status) throws
            ExceptionHelp {
        return null;
    }

    @Override
    public Tip billInpWork(Receive requestVal, HttpServletRequest request) {
        return null;
    }

    /**
     * 替换不属于HL7消息的节点字符串
     *
     * @param getHl7LabMessage
     * @return
     */
    public abstract String getReplaceString(BATCH getHl7LabMessage) throws ExceptionHelp;

    /**
     * 更新开单中相同节点数据
     *
     * @param clinicMaster
     * @param outpMedrec
     * @param outpOrderDescTempList
     * @param outpBillItemsTempList
     * @param outpDoctorAssistantList
     * @param objectMasterList
     * @param objectItemsList
     * @param objectBillitemsList
     * @param outpPrepayRcptTemp
     * @param orderVsBillnoList
     * @return
     * @throws ExceptionHelp
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAllTab(ClinicMaster clinicMaster, OutpMedrec
            outpMedrec, List<OutpOrderDescTemp> outpOrderDescTempList, List<OutpBillItemsTemp> outpBillItemsTempList,
                                List<OutpDoctorAssistant> outpDoctorAssistantList,
                                List<Object> objectMasterList, List<Object> objectItemsList, List<Object> objectBillitemsList,
                                OutpPrepayRcptTemp outpPrepayRcptTemp, List<OrderVsBillno> orderVsBillnoList) throws ExceptionHelp {
        boolean updateOtherTable = updateOtherTable(clinicMaster, outpMedrec, outpOrderDescTempList, outpBillItemsTempList,
                outpDoctorAssistantList,
                objectMasterList, objectItemsList, objectBillitemsList,
                outpPrepayRcptTemp, orderVsBillnoList);
        if (!updateOtherTable) {
            throw new ExceptionHelp(ExceptionHelpEnum.ORDER_OTHER_DETAIL_ERR);
        }
        return updateOtherTable;
    }

    /**
     * 更新检查或检验、处方等不同业务表中数据
     *
     * @param objectMasterList
     * @param objectItemsList
     * @param objectBillitemsList
     * @return
     */
    public abstract boolean updateOtherTable(ClinicMaster clinicMaster, OutpMedrec
            outpMedrec, List<OutpOrderDescTemp> outpOrderDescTempList, List<OutpBillItemsTemp> outpBillItemsTempList,
                                             List<OutpDoctorAssistant> outpDoctorAssistantList,
                                             List<Object> objectMasterList, List<Object> objectItemsList, List<Object> objectBillitemsList,
                                             OutpPrepayRcptTemp outpPrepayRcptTemp, List<OrderVsBillno> orderVsBillnoList) throws ExceptionHelp;

}
